﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using Common.Views;

namespace DataAccess
{
    public class ProductsRepository: ConnectionClass
    {
        public ProductsRepository() : base() { }

        public ProductsRepository(bool isAdmin) : base(isAdmin) { }

        public IQueryable<Product> GetAllProducts()
        {
            return Entity.Products;
        }

        public IQueryable<ProductComment> GetCommentsByProductID(int productID)
        {
            return Entity.ProductComments.Where(p => p.ProductID == productID).AsQueryable();
        }

        public Product GetProductById(int productID)
        {
            return Entity.Products.SingleOrDefault(p => p.ProductID == productID);
        }

        public void AddComment(ProductComment c)
        {
            Entity.AddToProductComments(c);
            Entity.SaveChanges();
        }

        public void AddProductRatings(ProductRating pr)
        {
            Entity.AddToProductRatings(pr);
            Entity.SaveChanges();
        }

        public IQueryable<int> GetUserRatings(string username, int productId)
        {
            return (
                from pr in Entity.ProductRatings
                where pr.ProductID == productId
                && pr.Username == username
                select pr.RatingNo
                );
        }

        public IQueryable<CartView> GetAllProductsByUsername(string username)
        {
            return (
                from p in Entity.Products
                join od in Entity.OrderDetails
                on p.ProductID equals od.ProductID
                join o in Entity.Orders
                on od.OrderID equals o.OrderID

                where o.Username == username
                
                select new CartView()
                {
                    ProductID = p.ProductID,
                    ProductName = p.ProductName
                }).AsQueryable();
        }

        public void AddToCart(Cart cart)
        {
            Entity.AddToCarts(cart);
            Entity.SaveChanges();
        }

        public Cart GetCart(string username, int productId)
        {
            return Entity.Carts.SingleOrDefault(u => u.Username == username && u.ProductID == productId);
        }

        public void UpdateCart(string username, int productId, int newQty)
        {
            Cart c = GetCart(username, productId);
            c.ProductQty += newQty;
            Entity.SaveChanges();
        }

        public IQueryable<CartView> GetProductsFromCart(string username)
        { 
            return (
                from c in Entity.Carts
                join p in Entity.Products
                on c.ProductID equals p.ProductID
                where c.Username == username
                    select new CartView
                    {
                        ProductID = p.ProductID,
                        ProductName = p.ProductName,
                        ProductImage = p.ImageLink,
                        Quantity = c.ProductQty,
                        Price = p.Price
                    }
                );
        }

        public void RemoveShoppingCart(Cart cart)
        {
            Entity.Carts.DeleteObject(cart);
            Entity.SaveChanges();
        }

        public void DecreaseStock(int productID, int qty)
        {
            Product p = (from pr in Entity.Products
                         where pr.ProductID == productID
                         select pr).SingleOrDefault();
            p.StockQty -= qty;
            Entity.SaveChanges();
        }

        public IQueryable<Cart> GetShoppingCartByUsername(string username)
        {
            return Entity.Carts.Where(u => u.Username == username);
        }

        public IQueryable<int> ReturnAverageRating(int productID)
        {
            return
                (
                from pr in Entity.ProductRatings
                where pr.ProductID == productID
                select pr.RatingNo
                );
        }

        public OrdersView GetProductDetails(int productID, Guid orderID)
        {
            return (
               from p in Entity.Products
               join od in Entity.OrderDetails
               on p.ProductID equals od.ProductID
               join o in Entity.Orders
               on od.OrderID equals o.OrderID

               where p.ProductID == productID &&
                    o.OrderID == orderID
               orderby o.DatePurchased descending

               select new OrdersView()
               {
                   OrderID = o.OrderID,
                   ProductID = p.ProductID,
                   ProductName = p.ProductName,
                   ImageLink = p.ImageLink,
                   UnitPrice = p.Price,
                   Features = p.Features,
                   Quantity = od.ProductQty,
                   OrderDate = o.DatePurchased,
                   WarrantyExpiryDate = od.WarrantyExpiryDate
               }).First();
        }

        public IEnumerable<Category> GetCategories()
        {
            return Entity.Categories;
        }

        public IQueryable<Product> GetProductsByCategoryRefinement(int categoryID)
        {
            return Entity.Products.Where(p => p.CategoryID == categoryID);
        }

        public IEnumerable<Product> SearchProductByName(string keyword)
        {
            return Entity.Products.Where(p => p.ProductName.Contains(keyword));
        }

        public IEnumerable<Product> SearchProductByPrice(decimal minPrice, decimal maxPrice)
        {
            return Entity.Products.Where(p => (p.Price >= minPrice) && (p.Price <= maxPrice));
        }

        public IEnumerable<Product> SearchProductByPriceASC()
        {
            return Entity.Products.OrderBy(p => p.Price);
        }

        public IEnumerable<Product> SearchProductByPriceDESC()
        {
            return Entity.Products.OrderByDescending(p => p.Price);
        }

        public IEnumerable<Product> SearchProductByDateASC()
        {
            return Entity.Products.OrderByDescending(p => p.DateListed);
        }
    }
}
